package com.jingdianjichi.auth.service.impl;


import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import com.jingdianjichi.auth.common.enums.AuthUserStatusEnum;
import com.jingdianjichi.auth.common.enums.IsDeletedFlageEnum;
import com.jingdianjichi.auth.domain.constants.AuthConstant;
import com.jingdianjichi.auth.domain.convert.AuthUserBOConverter;
import com.jingdianjichi.auth.domain.entity.AuthUserBO;
import com.jingdianjichi.auth.infra.basic.entity.AuthPermission;
import com.jingdianjichi.auth.infra.basic.entity.AuthRole;
import com.jingdianjichi.auth.infra.basic.entity.AuthRolePermission;
import com.jingdianjichi.auth.infra.basic.entity.AuthUser;
import com.jingdianjichi.auth.infra.basic.service.*;
import com.jingdianjichi.auth.redis.RedisUtil;
import com.jingdianjichi.auth.service.AuthUserDomainService;
import com.jingdianjichi.subject.infra.basic.entity.AuthUserRole;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户信息表(AuthUser)表服务实现类
 *
 * @author makejava
 * @since 2024-04-14 23:18:26
 */
@Service
@Slf4j
public class AuthUserDomainServiceImpl implements AuthUserDomainService {
    @Resource
    private AuthUserService authUserService;
    @Resource
    private AuthUserRoleService authUserRoleService;
    @Resource
    private AuthRoleService authRoleService;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private AuthPermissionService authPermissionService;
    @Resource
    private AuthRolePermissionService authRolePermissionService;
    private String authPermissionPrefix = "auth.permission";
    private String authRolePrefix = "auth.role";
    private String publicKey = "jichi";
    private static final String LOGIN_PREFIX = "loginCode";

    @Override
    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    public Boolean register(AuthUserBO authUserBO) {
        if (log.isInfoEnabled()) {
            log.info("AuthUserDomainServiceImpl.register.dto:{}", JSON.toJSONString(authUserBO));
        }

        //校验用户是否存在
        AuthUser existAuthUser = new AuthUser();
        existAuthUser.setUserName(authUserBO.getUserName());
        List<AuthUser> existUser = authUserService.queryByCondition(existAuthUser);
        if (existUser.size() > 0) {
            return true;
        }
//     HashMap<String,String> keyMap= SaSecureUtil.rsaGenerateKeyPair();
//
//        String privateKey = keyMap.get("private");
//        String publicKey = keyMap.get("publick");
//        authUser.setPassword(SaSecureUtil.rsaEncryptByPublic(publicKey,authUser.getPassword()));
//        //怎么解密
//        log.info("解密==》，{}", SaSecureUtil.rsaDecryptByPrivate(privateKey,authUser.getPassword()));
        AuthUser authUser = AuthUserBOConverter.INSTANCE.convertBOto(authUserBO);
        if (StringUtils.isNoneBlank(authUser.getPassword())) {
            //密码加密
            authUser.setPassword(SaSecureUtil.md5BySalt(authUser.getPassword(), publicKey));
        }
        authUser.setStatus(AuthUserStatusEnum.OPEN.getCode());
        authUser.setIsDeleted(IsDeletedFlageEnum.UN_DELETE.getCode());

        Integer count = authUserService.insert(authUser);
        // ：建立一个初步的角色关联
        //查询角色
        AuthRole authRole = new AuthRole();
        authRole.setRoleKey(AuthConstant.NORMAL_USER);
        AuthRole authRoleResult = authRoleService.queryByCondition(authRole);
        Long RoleId = authRoleResult.getId();
        Long UserId = authUser.getId();
        //角色和用户关联
        AuthUserRole authUserRole = new AuthUserRole();
        authUserRole.setUserId(UserId);
        authUserRole.setRoleId(RoleId);
        authUserRole.setIsDeleted(IsDeletedFlageEnum.UN_DELETE.getCode());
        Integer result = authUserRoleService.insert(authUserRole);
        //要把单前用户的角色和权限都刷到redis中
        //角色
        String roleKey = redisUtil.buildKey(authRolePrefix, authUser.getUserName());
        List<AuthRole> roleList = new LinkedList<>();
        roleList.add(authRole);
        //角色存入redis
        redisUtil.set(roleKey, new Gson().toJson(roleList));
        //权限
        //根据RoleId 从权限角色关联表查出权限id
        AuthRolePermission authRolePermission = new AuthRolePermission();
        authRolePermission.setRoleId(RoleId);
        List<AuthRolePermission> rolePermissionList = authRolePermissionService.queryByCondition(authRolePermission);
        //获取全部PermissionId
        List<Long> permissionIdList = rolePermissionList.stream()
                .map(AuthRolePermission::getPermissionId).collect(Collectors.toList());

        List<AuthPermission> authPermissionList = authPermissionService.queryByPerIdList(permissionIdList);
        String permissionKey = redisUtil.buildKey(authPermissionPrefix, authUser.getUserName());
        //把权限刷到redis中
        redisUtil.set(permissionKey, new Gson().toJson(authPermissionList));
        return count > 0 && result > 0;
    }

    @Override
    public Boolean update(AuthUserBO authUserBO) {
        if (log.isInfoEnabled()) {
            log.info("AuthUserDomainServiceImpl.update.dto:{}", JSON.toJSONString(authUserBO));
        }
        AuthUser authUser = AuthUserBOConverter.INSTANCE.convertBOto(authUserBO);
        Integer count = authUserService.update(authUser);
        //todo ：有任何更新，都要与缓存进行同步

        return count > 0;
    }

    @Override
    public Boolean delete(AuthUserBO authUserBO) {
        if (log.isInfoEnabled()) {
            log.info("AuthUserDomainServiceImpl.delete.dto:{}", JSON.toJSONString(authUserBO));
        }
        AuthUser authUser = AuthUserBOConverter.INSTANCE.convertBOto(authUserBO);
        authUser.setIsDeleted(IsDeletedFlageEnum.DELETE.getCode());
        Integer count = authUserService.update(authUser);
        //todo ：有任何更新，都要与缓存进行同步

        return count > 0;
    }

    @Override
    public Boolean changeStatus(AuthUserBO authUserBO) {
        if (log.isInfoEnabled()) {
            log.info("AuthUserDomainServiceImpl.changeStatus.dto:{}", JSON.toJSONString(authUserBO));
        }
        AuthUser authUser = AuthUserBOConverter.INSTANCE.convertBOto(authUserBO);

        Integer count = authUserService.update(authUser);
        //todo ：有任何更新，都要与缓存进行同步

        return count > 0;
    }

    @Override
    public AuthUserBO getUserInfo(AuthUserBO authUserBO) {
        if (log.isInfoEnabled()) {
            log.info("AuthUserDomainServiceImpl.getUserInfo.dto:{}", JSON.toJSONString(authUserBO));
        }
//        AuthUser authUser = AuthUserBOConverter.INSTANCE.convertBOto(authUserBO);
//        authUser.setIsDeleted(IsDeletedFlageEnum.UN_DELETE.getCode());
        AuthUser authUser = new AuthUser();
        authUser.setUserName(authUserBO.getUserName());
        List<AuthUser> userList = authUserService.queryByCondition(authUser);
        if (CollectionUtils.isEmpty(userList)) {
            return new AuthUserBO();
        }
        AuthUser user = userList.get(0);
        AuthUserBO authUserBOResult = AuthUserBOConverter.INSTANCE.converttoBO(user);
        //todo ：有任何更新，都要与缓存进行同步

        return authUserBOResult;
    }

    @Override
    public SaTokenInfo doLogin(String validCode) {
        String loginKey = redisUtil.buildKey(LOGIN_PREFIX, validCode);
        String openId = redisUtil.get(loginKey);
        if (StringUtils.isBlank(openId)) {
            return null;
        }
        AuthUserBO authUserBO = new AuthUserBO();
        authUserBO.setUserName(openId);
        //注册
        this.register(authUserBO);
        // 第1步，先登录上
        StpUtil.login(openId);
        // 第2步，获取 Token  相关参数
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        return tokenInfo;
    }
}
